/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.web.common.verifycode;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import jakarta.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * 图形验证码生成组件
 *
 * @author yoara
 */
@Component
public class VerifyCodeComponent {
    private static Log logger = LogFactory.getLog(VerifyCodeComponent.class);
    private static final String CONTENT_TYPE = "image/jpeg";
    private static final int WIDTH = 64;
    private static final int HEIGHT = 22;
    public final static String VERIFY_CODE_SESSION_TEMPORARY = "VERIFY_CODE_SESSION_TEMPORARY";

    private static final char[] PARAM = { '3', '4', '5', '6', '7', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'k',
            'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'A', 'C', 'D', 'E', 'F', 'G', 'H', 'K', 'M',
            'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y' };
    private static final int PARAM_LENGTH = PARAM.length; // 62

    /**
     * 获得字符串图形验证码
     */
    public void codeImageGet(VerifyCodeParam param){
        param.getResponse().setContentType(CONTENT_TYPE);
        int width = param.getCustomCodeImgWidth()==null?WIDTH:param.getCustomCodeImgWidth();
        int height = param.getCustomCodeImgHeight()==null?HEIGHT:param.getCustomCodeImgHeight();

        try {
            Random ran = new Random();
            StringBuilder sb = new StringBuilder();
            // 产生验证码
            for (int i = 0; i < 4; i++) {
                char temp = PARAM[Math.abs((ran.nextInt()) % PARAM_LENGTH)];
                while (sb.indexOf(String.valueOf(temp)) != -1) {
                    temp = PARAM[Math.abs((ran.nextInt()) % PARAM_LENGTH)];
                }
                sb.append(temp).append("");
            }
            // 将验证码保存到Session中
            param.getRequest().getSession().setAttribute(VERIFY_CODE_SESSION_TEMPORARY, sb.toString());

            // 输出图片到页面
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = (Graphics2D) image.getGraphics();
            g.setColor(new Color(255, 255, 255));
            g.fillRect(0, 0, width, height);

            for (int i = 0; i < 18; i++) {
                g.setColor(new Color(ran.nextInt(100) + 110, ran.nextInt(100) + 110, ran.nextInt(100) + 110));
                int x_b = ran.nextInt(width);
                int x_e = ran.nextInt(width);
                int y_b = ran.nextInt(height + 1);
                int y_e = ran.nextInt(height + 1);
                g.drawLine(x_b, y_b, x_e, y_e);
            }

            g.setFont(new Font("System", Font.BOLD, 18));
            g.setColor(new Color(0, 0, 255));
            g.drawString(sb.toString(), 5, 15);
            g.dispose();
            ImageIO.write(image, "jpg", param.getResponse().getOutputStream());
        } catch (Exception ex) {
            logger.error("doPost error.", ex);
        }
    }

    /**
     * 校验字符图形验证码
     * @param code
     * @param request
     * @return
     */
    public boolean codeImageValidate(String code,HttpServletRequest request){
        VerifyCodeForm form = new VerifyCodeForm();
        form.setCode(code);
        return codeImageValidate(form,request);
    }

    /**
     * 校验字符图形验证码
     * @param form
     * @param request
     * @return
     */
    public boolean codeImageValidate(VerifyCodeForm form,HttpServletRequest request){
        String rightCode = (String)request.getSession().getAttribute(VERIFY_CODE_SESSION_TEMPORARY);

        if (StringUtils.isNotEmpty(rightCode) && StringUtils.isNotEmpty(form.getCode())
                && rightCode.equalsIgnoreCase(form.getCode())) {
            request.getSession().removeAttribute(VERIFY_CODE_SESSION_TEMPORARY);
            return true;
        } else {
            return false;
        }
    }
}
